#include "tcp_server_select.h"
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdbool.h>
#include <strings.h>
#include <string.h>
#include <sys/select.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include "socket_tool.h"

void start_tcp_server_select()
{
    puts("启动server_select");

    // 先创建套接字
    int listen_fd = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in server_ip;
    bzero(&server_ip, sizeof(server_ip));
    server_ip.sin_family = AF_INET;
    server_ip.sin_addr.s_addr = htonl(INADDR_ANY);
    server_ip.sin_port = htons(12345);
    
    bind(listen_fd, (struct sockaddr*) &server_ip, sizeof(server_ip));
    listen(listen_fd, 5);


    struct sockaddr_in client_ip;
    socklen_t client_len = sizeof(client_ip);
    bzero(&client_ip, client_len);

    // 客户端连接套接字集合
    size_t arr_len = FD_SETSIZE;
    int client_fd_arr[arr_len];
    for (size_t i = 0; i < arr_len; i++)
        client_fd_arr[i] = -1;
    
    fd_set all_set, read_set;
    FD_ZERO(&all_set);
    FD_SET(listen_fd, &all_set);

    char buf[256];
    bzero(buf, sizeof(buf));
    while (true)
    {
        puts("继续运行");
        int maxfd = listen_fd;
        // 取得最大的fd
        for (size_t i = 0; i < arr_len; i++)
        {
            if (client_fd_arr[i] > maxfd)
                maxfd = client_fd_arr[i];
        }
        
        read_set = all_set;
        int ready_count = select(maxfd + 1, &read_set, NULL, NULL, NULL);

        if (FD_ISSET(listen_fd, &read_set)) {
            int client_fd = accept(listen_fd, (struct sockaddr*) &client_ip, &client_len);
            if (client_fd < 0) {
                puts("accept等待连接失败");
                exit(-1);
            }

            // 放到连接套接字集合中
            size_t i = 0;
            for ( ;i < arr_len; i++)
            {
                if (client_fd_arr[i] == -1) {
                    client_fd_arr[i] = client_fd;
                    break;
                }
            }
            if (i >= arr_len) {
                puts("客户端太多，拒绝连接");
                exit(-1);
            }
            FD_SET(client_fd, &all_set);
            ready_count--;
            char *client_info = sockaddr_to_string(&client_ip);
            printf("连接成功，client=%s\n", client_info);
            free(client_info);
        }

        for (size_t i = 0; i < arr_len && ready_count > 0; i++) 
        {
            int cli_fd = client_fd_arr[i];
            if (cli_fd == -1)
                continue;
            if (FD_ISSET(cli_fd, &read_set)) {
                ready_count--;
                // 客户i套接字可读
                int read_bytes = read(cli_fd, buf, sizeof(buf));
                if (read_bytes <= 0) {
                    printf("读取client_fd = %d 失败或客户关闭连接，关闭客户连接\n", cli_fd);
                    client_fd_arr[i] = -1;
                    FD_CLR(cli_fd, &all_set);
                    close(cli_fd);
                    continue;
                }
                printf("client_fd = %d say:%s", cli_fd, buf);
                if (strcmp("bye\n", buf) == 0) {
                    printf("client_fd = %d 发送bye关闭连接\n", cli_fd);
                    client_fd_arr[i] = -1;
                    FD_CLR(cli_fd, &all_set);
                    close(cli_fd);
                    continue;
                }
                // 回射给客户
                write(cli_fd, buf, strlen(buf));
            }
        }

    }
    

}